package com.stevenmoon.csdnplus.net;

import android.text.TextUtils;

import com.google.gson.reflect.TypeToken;
import com.orhanobut.logger.Logger;
import com.stevenmoon.csdnplus.app.AppService;
import com.stevenmoon.csdnplus.bean.ResponseResultBean;

import java.io.IOException;
import java.lang.reflect.Type;

import okhttp3.Response;
import rx.Observable;
import rx.functions.Func1;

/**
 * Created by WangJun on 2016/3/31.
 */
public class RxNet {


    /**
     * rx方式的post请求
     *
     * @param info    请求信息
     * @param resType 形如： Type t = new TypeToken<ResponseResultBean<AccountBean>>() {}.getType();
     * @param <T>     响应的实体bean，如：AccountBean
     * @return 返回解析好的ResponseResultBean的Observable
     */
    public static <T> Observable<ResponseResultBean<T>> post(RequestParams info, final TypeToken<ResponseResultBean<T>> resType) {
        return getResponseBean(getPostResponseString(info), resType.getType());

    }

    /**
     * rx方式的post请求
     *
     * @param info    请求信息
     * @param resType 形如： Type t = new TypeToken<ResponseResultBean<AccountBean>>() {}.getType();
     * @param <T>     响应的实体bean，如：AccountBean
     * @return 返回解析好的实体bean的Observable
     */
    public static <T> Observable<T> postAndFetchEntity(RequestParams info, final TypeToken<ResponseResultBean<T>> resType) {
        return getEntityBean(getPostResponseString(info),resType.getType());

    }

    /**
     * rx方式的get请求
     *
     * @param info    请求信息
     * @param resType 形如： Type t = new TypeToken<ResponseResultBean<AccountBean>>() {}.getType();
     * @param <T>     响应的实体bean，如：AccountBean
     * @return 返回解析好的实体bean的Observable
     */
    public static <T> Observable<T> getAndFetchEntity(RequestParams info, final TypeToken<ResponseResultBean<T>> resType) {
        return getEntityBean(getGetResponseString(info),resType.getType());

    }

    /**
     * rx方式的get请求
     *
     * @param info    请求信息
     * @param resType 形如： Type t = new TypeToken<ResponseResultBean<AccountBean>>() {}.getType();
     * @param <T>     响应的实体bean，如：AccountBean
     * @return 返回解析好的ResponseResultBean的Observable
     */
    public static <T> Observable<ResponseResultBean<T>> get(RequestParams info, final Type resType) {
        return getResponseBean(getGetResponseString(info), resType);
    }


    private static Observable<String> getPostResponseString(RequestParams info) {
        return Observable.just(info)
                .flatMap(new Func1<RequestParams, Observable<String>>() {
                    @Override
                    public Observable<String> call(RequestParams requestInfo) {
                        Response response = null;
                        try {
                            response = CSDNNetUtil.post()
                                    .url(requestInfo.getUrl())
                                    .addParams(requestInfo.getParamsMap())
                                    .build()
                                    .execute();
                            String responseStr = response.body().string();
                            return Observable.just(responseStr);
                        } catch (Exception e) {
                            e.printStackTrace();
                            Logger.e(e,"getPostResponseString");
                            return Observable.error(new IOException("网络连接失败，请检查网络"));
                        }

                    }
                });
    }

    private static Observable<String> getGetResponseString(RequestParams info) {
        return Observable.just(info)
                .flatMap(new Func1<RequestParams, Observable<String>>() {
                    @Override
                    public Observable<String> call(RequestParams requestInfo) {
                        Response response = null;
                        try {
                            response = CSDNNetUtil.get()
                                    .url(requestInfo.getUrl())
                                    .addParams(requestInfo.getParamsMap())
                                    .build()
                                    .execute();
                            String responseStr = response.body().string();
                            return Observable.just(responseStr);
                        } catch (Exception e) {
                            e.printStackTrace();
                            Logger.e(e,"getGetResponseString");
                            return Observable.error(new IOException("网络连接失败，请检查网络"));
                        }

                    }
                });
    }


    private static <T> Observable<ResponseResultBean<T>> getResponseBean(Observable<String> resString, final Type resType) {
        return resString
                .flatMap(new Func1<String, Observable<ResponseResultBean<T>>>() {
                    @Override
                    public Observable<ResponseResultBean<T>> call(String s) {
                        ResponseResultBean<T> resultBean = null;
                        try{
                            resultBean = AppService.getInstance().getGson().fromJson(s, resType);
                        }catch (Exception e){
                            e.printStackTrace();
                            Logger.e(e,"ResponseStr--"+s);
                            return Observable.error(new Throwable("数据解析错误"));
                        }

                        switch (resultBean.code) {
                            case ResponseResultBean.CODE_UNAUTHORIZED:
                                //TODO 未授权，是否要自动重新登录？或者退出到登录界面
//                                new IllegalAccessException("授权失败，请重新登录")
                                String msg = resultBean.message;
                                if (TextUtils.isEmpty(msg)) {
                                    msg = "授权失败，请重新登录";
                                }
                                return Observable.error(new Throwable(msg));
                            case ResponseResultBean.CODE_BAD_REQUEST:
//                                new IllegalAccessException("请求失败，请重试")
                                msg = resultBean.message;
                                if (TextUtils.isEmpty(msg)) {
                                    msg = "请求失败，请重试";
                                }
                                return Observable.error(new Throwable(msg));
                            case ResponseResultBean.CODE_SUCCESS:
                            default:
                                return Observable.just(resultBean);
                        }

                    }
                });
    }

    private static <T> Observable<T> getEntityBean(Observable<String> resString, final Type resType) {
        Observable<ResponseResultBean<T>> oo = getResponseBean(resString,resType);
        return oo.flatMap(new Func1<ResponseResultBean<T>, Observable<T>>() {
            @Override
            public Observable<T> call(ResponseResultBean<T> tResponseResultBean) {
                return Observable.just(tResponseResultBean.data);
            }
        });
    }


}
